﻿@page "/system/picklistset"
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.DTOs
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Queries.Export
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Queries.PaginationQuery
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Caching
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Commands.AddEdit
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Commands.Delete
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Commands.Import
@using CleanArchitecture.Blazor.Application.Features.PicklistSets.Specifications
@using CleanArchitecture.Blazor.Server.UI.Pages.PicklistSets.Components

@attribute [Authorize(Policy = Permissions.PicklistSets.View)]
@inject IStringLocalizer<PicklistSets> L
@inject BlazorDownloadFileService BlazorDownloadFileService

<PageTitle>@Title</PageTitle>

<MudDataGrid @ref="_table" FixedHeader="true"
             FixedFooter="false"
             @bind-RowsPerPage="_defaultPageSize"
             Hover="true"
             MultiSelection="true"
             @bind-SelectedItems="_selectedItems"
             ReadOnly="false"
             EditMode="DataGridEditMode.Cell"
             T="PicklistSetDto"
             CommittedItemChanges="@CommittedItemChanges"
             ServerData="ServerReload">
    <ToolBarContent>
        <MudStack Row Spacing="0" Class="flex-grow-1" Justify="Justify.SpaceBetween">
            <!-- Left Toolbar: Icon, Title and List View -->
            <MudStack Row AlignItems="AlignItems.Start">
                <MudIcon Icon="@Icons.Material.Filled.ViewList" Size="Size.Large" />
                <MudStack Spacing="0">
                    <MudText Typo="Typo.subtitle2" Class="mb-2">@Title</MudText>
                    <MudEnumSelect Style="min-width:120px" TEnum="PickListView" Value="_picklistQuery.ListView" 
                                     ValueChanged="OnChangedListView" Dense="true" Label="@L["List View"]">
                    </MudEnumSelect>
                </MudStack>
            </MudStack>
            <!-- Right Toolbar: Actions and Search -->
            <MudStack Spacing="0" AlignItems="AlignItems.End">
                <MudToolBar Dense WrapContent="true" Class="py-1 px-0">
                    <MudButton Disabled="@_loading"
                               OnClick="OnRefresh"
                               StartIcon="@Icons.Material.Outlined.Refresh">
                        @ConstantString.Refresh
                    </MudButton>
                    @if (_accessRights.Create)
                    {
                        <MudButton StartIcon="@Icons.Material.Outlined.Add"
                        OnClick="OnCreate">
                            @ConstantString.New
                        </MudButton>
                    }
                    <MudMenu TransformOrigin="Origin.BottomRight" AnchorOrigin="Origin.BottomRight" EndIcon="@Icons.Material.Filled.MoreVert" Label="@ConstantString.More">
                        @if (_accessRights.Delete)
                        {
                            <MudMenuItem Disabled="@(_selectedItems.Count == 0)"
                            OnClick="OnDeleteChecked">
                                @ConstantString.Delete
                            </MudMenuItem>
                        }
                        @if (_accessRights.Export)
                        {
                            <MudMenuItem Disabled="@_exporting"
                            OnClick="OnExport">
                                @ConstantString.Export
                            </MudMenuItem>
                        }
                        @if (_accessRights.Import)
                        {
                            <MudMenuItem>
                                <MudFileUpload T="IBrowserFile" FilesChanged="OnImportData" Accept=".xlsx">
                                    <ActivatorContent>
                                        <MudButton Class="pa-0 ma-0"
                                        Style="font-weight:400;text-transform:none;"
                                        Variant="Variant.Text"
                                        Disabled="@_uploading">
                                            @ConstantString.Import
                                        </MudButton>
                                    </ActivatorContent>
                                </MudFileUpload>
                            </MudMenuItem>
                        }
                    </MudMenu>
                </MudToolBar>
                <MudStack Row Spacing="1">
                    @if (_accessRights.Search)
                    {
                        <MudEnumSelect TEnum="Picklist?" Placeholder="@L["Search by picklist"]" Value="@_searchPicklist" Clearable="true" 
                        ValueChanged="OnPicklistSearch" Style="width:160px" FullWidth="true" />
                        <MudTextField T="string" Value="@_picklistQuery.Keyword" ValueChanged="OnKeywordSearch" Placeholder="@ConstantString.Search" 
                        Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Small" />
                    }
                </MudStack>
            </MudStack>
        </MudStack>
    </ToolBarContent>
    <Columns>
        <PropertyColumn Property="x => x.Name" Title="@L[SelectedItem.GetMemberDescription(x => x.Name)]">
            <EditTemplate>
                <MudEnumSelect @bind-Value="@context.Item.Name" TEnum="Picklist" OnClose="@(() => PicklistChanged(context.Item))" Required="true">
                </MudEnumSelect>
            </EditTemplate>
        </PropertyColumn>
        <PropertyColumn Property="x => x.Value" Title="@L[SelectedItem.GetMemberDescription(x => x.Value)]" />
        <PropertyColumn Property="x => x.Text" Title="@L[SelectedItem.GetMemberDescription(x => x.Text)]" />
        <PropertyColumn Property="x => x.Description" Title="@L[SelectedItem.GetMemberDescription(x => x.Description)]" />
        <TemplateColumn HeaderStyle="width:60px" Title="@ConstantString.Delete" Sortable="false">
            <CellTemplate>
                <MudIconButton Icon="@Icons.Material.Filled.Delete" Variant="Variant.Outlined" Color="Color.Error" aria-label="@ConstantString.Delete" Disabled="@(!_accessRights.Delete)" Size="Size.Small" OnClick="@(() => DeleteItem(context.Item))" />
            </CellTemplate>
            <EditTemplate>
                <MudIconButton Icon="@Icons.Material.Filled.Delete" Variant="Variant.Outlined" Color="Color.Error" aria-label="@ConstantString.Delete" Disabled="@(!_accessRights.Delete)" Size="Size.Small" OnClick="@(() => DeleteItem(context.Item))" />
            </EditTemplate>
        </TemplateColumn>
    </Columns>
    <PagerContent>
        <MudDataGridPager PageSizeOptions="@(new[] { 10, 15, 30, 50, 100, 500, 1000 })" />
    </PagerContent>
</MudDataGrid>

@code {
    #region Fields & Properties

    [CascadingParameter] private Task<AuthenticationState> AuthState { get; set; } = default!;
    [CascadingParameter] private UserProfile? UserProfile { get; set; }
    private MudDataGrid<PicklistSetDto> _table = null!;
    public string Title { get; set; } = "Picklist";
    private IList<PicklistSetDto> _keyValueList = new List<PicklistSetDto>();
    private HashSet<PicklistSetDto> _selectedItems = new();
    private PicklistSetDto SelectedItem { get; set; } = new();
    private PicklistSetDto ElementBeforeEdit { get; set; } = new();

    private string _searchString = string.Empty;
    private Picklist? _searchPicklist;
    private int _defaultPageSize = 15;

    private PicklistSetsWithPaginationQuery _picklistQuery { get; set; } = new();
    private PicklistSetsAccessRights _accessRights = new();
 

    private bool _loading;
    private bool _uploading;
    private bool _exporting;

    #endregion



    protected override async Task OnInitializedAsync()
    {
        Title = L[SelectedItem.GetClassDescription()];
        _accessRights = await PermissionService.GetAccessRightsAsync<PicklistSetsAccessRights>();
    }
     


    #region Grid Data & Search

    private async Task<GridData<PicklistSetDto>> ServerReload(GridState<PicklistSetDto> state)
    {
        try
        {
            _loading = true;
            _picklistQuery.CurrentUser = UserProfile;
            _picklistQuery.Keyword = _searchString;
            _picklistQuery.Picklist = _searchPicklist;
            _picklistQuery.OrderBy = state.SortDefinitions.FirstOrDefault()?.SortBy ?? "Id";
            _picklistQuery.SortDirection = (state.SortDefinitions.FirstOrDefault()?.Descending ?? true)
                                  ? SortDirection.Descending.ToString()
                                  : SortDirection.Ascending.ToString();
            _picklistQuery.PageNumber = state.Page + 1;
            _picklistQuery.PageSize = state.PageSize;
            var result = await Mediator.Send(_picklistQuery);
            return new GridData<PicklistSetDto> { TotalItems = result.TotalItems, Items = result.Items };
        }
        finally
        {
            _loading = false;
        }
    }

    private async Task OnChangedListView(PickListView listview)
    {
        _picklistQuery.ListView = listview;
        await _table.ReloadServerData();
    }

    private async Task OnKeywordSearch(string text)
    {
        _searchString = text;
        await _table.ReloadServerData();
    }

    private async Task OnPicklistSearch(Picklist? val)
    {
        _searchPicklist = val;
        await _table.ReloadServerData();
    }

    private async Task OnRefresh()
    {
        PicklistSetCacheKey.Refresh();
        _searchString = string.Empty;
        await InvokeAsync(() => _table.ReloadServerData());
    }

    #endregion

    #region Edit & Commit Changes

    private void PicklistChanged(PicklistSetDto item)
    {
        // Trigger the commit of cell changes.
        _table.CommittedItemChanges.InvokeAsync(item);
    }

    private void CommittedItemChanges(PicklistSetDto item)
    {
        InvokeAsync(async () =>
        {
            var command = Mapper.Map<AddEditPicklistSetCommand>(item);
            var result = await Mediator.Send(command);
            if (!result.Succeeded)
            {
                Snackbar.Add(result.ErrorMessage, Severity.Error);
            }
            StateHasChanged();
        });
    }

    #endregion

    #region Create & Delete

    private Task OnCreate()
    {
        var command = new AddEditPicklistSetCommand
        {
            Name = SelectedItem.Name,
            Description = SelectedItem?.Description
        };
        return DialogServiceHelper.ShowFormDialogAsync<CreatePicklistDialog, AddEditPicklistSetCommand>(
             L["Create a picklist"],
            command,
            async () =>
            {
                await _table.ReloadServerData();
                _selectedItems.Clear();
            });
         
    }

    private async Task DeleteItem(PicklistSetDto item)
    {
        var command = new DeletePicklistSetCommand(new[] { item.Id });
        var contentText = string.Format(ConstantString.DeleteConfirmation, item.Name);
        await DialogServiceHelper.ShowDeleteConfirmationDialogAsync(command, ConstantString.DeleteConfirmationTitle, contentText, async () =>
        {
            await InvokeAsync(async () =>
            {
                await _table.ReloadServerData();
                _selectedItems.Clear();
            });
        });
    }

    private async Task OnDeleteChecked()
    {
        var command = new DeletePicklistSetCommand(_selectedItems.Select(x => x.Id).ToArray());
        var contentText = string.Format(ConstantString.DeleteConfirmation, _selectedItems.Count);
        await DialogServiceHelper.ShowDeleteConfirmationDialogAsync(command, ConstantString.DeleteConfirmationTitle, contentText, async () =>
        {
            await InvokeAsync(async () =>
            {
                await _table.ReloadServerData();
                _selectedItems.Clear();
            });
        });
    }

    #endregion

    #region Export & Import

    private async Task OnExport()
    {
        _exporting = true;
        try
        {
            var request = new ExportPicklistSetsQuery { Keyword = _searchString };
            var result = await Mediator.Send(request);
            await BlazorDownloadFileService.DownloadFileAsync($"{L["Picklist"]}.xlsx", result, "application/octet-stream");
            Snackbar.Add(ConstantString.ExportSuccess, Severity.Info);
        }
        finally
        {
            _exporting = false;
        }
    }

    private async Task OnImportData(IBrowserFile file)
    {
        _uploading = true;
        try
        {
            using var stream = new MemoryStream();
            await file.OpenReadStream(GlobalVariable.MaxAllowedSize).CopyToAsync(stream);
            var command = new ImportPicklistSetsCommand(file.Name, stream.ToArray());
            var result = await Mediator.Send(command);
            if (result.Succeeded)
            {
                await OnRefresh();
                Snackbar.Add(ConstantString.ImportSuccess, Severity.Info);
            }
            else
            {
                foreach (var msg in result.Errors)
                {
                    Snackbar.Add(msg, Severity.Error);
                }
            }
        }
        finally
        {
            _uploading = false;
        }
    }

    #endregion
}
